#include <fstream>
#include <iostream>
#include <pthread.h>
#include "icemanager.h"
#include "fileexchange.h"

void writeCandidatesToFile( std::string username, std::string password, std::vector<ICECandidate> cands, std::string filename )
{
    std::cout << "Abrindo arquivo " << filename << " para escrita" << std::endl;
    std::ofstream ofs( filename.c_str() );

    if( !ofs.is_open() )
    {
        std::cout << "Erro ao abrir o arquivo!" << std::endl;
        return;
    }
    std::cout << "Escrevendo candidatos..." << std::endl;

    ofs << username << std::endl;
    ofs << password << std::endl;

    ofs << cands.size() << std::endl;
    for( unsigned int i = 0; i < cands.size(); i++ )
    {
        ofs << cands[i].getComponent() << std::endl;
        ofs << cands[i].getFoundation() << std::endl;
        ofs << cands[i].getIp() << std::endl;
        ofs << cands[i].getNetwork() << std::endl;
        ofs << cands[i].getPort() << std::endl;
        ofs << cands[i].getPriority() << std::endl;
        ofs << cands[i].getProtocol() << std::endl;
        ofs << cands[i].getRelAddr() << std::endl;
        ofs << cands[i].getRelPort() << std::endl;
        ofs << cands[i].getType() << std::endl;
    }
    std::cout << "Escrita completa!" << std::endl;

    ofs.close();
}

std::vector<ICECandidate> readCandidatesFromFile( std::string &username, std::string &password, std::string filename )
{
    std::vector<ICECandidate> cands;

    std::cout << "Abrindo arquivo " << filename << " para leitura" << std::endl;
    std::ifstream ifs( filename.c_str() );

    if( !ifs.is_open() )
    {
        std::cout << "Erro ao abrir o arquivo!" << std::endl;
        return cands;
    }
    std::cout << "Lendo candidatos..." << std::endl;

    ifs >> username;
    ifs >> password;

    unsigned int n_cands;
    ifs >> n_cands;
    for( unsigned int i = 0; i < n_cands; i++ )
    {
        cands.push_back( ICECandidate() );
        unsigned int value;
        std::string str;

        ifs >> value;
        cands[i].setComponent( value );
        ifs >> str;
        cands[i].setFoundation( str );
        ifs >> str;
        cands[i].setIp( str );
        ifs >> value;
        cands[i].setNetwork( value );
        ifs >> value;
        cands[i].setPort( value );
        ifs >> value;
        cands[i].setPriority( value );
        ifs >> str;
        cands[i].setProtocol( str );
        ifs >> str;
        cands[i].setRelAddr( str );
        ifs >> value;
        cands[i].setRelPort( value );
        ifs >> str;
        cands[i].setType( str );
    }
    std::cout << "Leitura completa!" << std::endl;

    ifs.close();

    return cands;
}

void printCandidates( std::vector<ICECandidate> cands )
{
    // List candidates
    std::cout << std::endl << std::endl << cands.size() << " candidato(s):" << std::endl << std::endl;
    for( unsigned int i = 0; i < cands.size(); i++ )
    {
        std::cout << "[Candidato " << i << "]" << std::endl;
        std::cout << "component = " << cands[i].getComponent() << std::endl;
        std::cout << "foundation = " << cands[i].getFoundation() << std::endl;
        std::cout << "ip = " << cands[i].getIp() << std::endl;
        std::cout << "network = " << cands[i].getNetwork() << std::endl;
        std::cout << "port = " << cands[i].getPort() << std::endl;
        std::cout << "priority = " << cands[i].getPriority() << std::endl;
        std::cout << "protocol = " << cands[i].getProtocol() << std::endl;
        std::cout << "rel-addr = " << cands[i].getRelAddr() << std::endl;
        std::cout << "rel-port = " << cands[i].getRelPort() << std::endl;
        std::cout << "type = " << cands[i].getType() << std::endl << std::endl;
    }
}

void receive( guint size, gchar* data, guint component_id )
{
    std::cout << "CompId: " << component_id << "    Size: " << size << "    Data: " << data << std::endl;
}

int main( int argc, char *argv[] )
{
    std::string remote_username, remote_password, turn_username, turn_password;
    std::vector<ICECandidate> lcands, rcands;
    ICEManager icemgr;
    ICEServer *stun_server, *turn_server;
    bool use_turn = false;

    if( argc == 3 )
    {
        std::cout << "[TURN Credentials]" << std::endl;
        turn_username = argv[1];
        turn_password = argv[2];
        std::cout << "Username: " << turn_username << std::endl;
        std::cout << "Password: " << turn_password << std::endl;
        use_turn = true;
    }
    else
    {
        turn_username = "";
        turn_password = "";
    }
    
    // STUN e TURN Server - Numb
    ICEServer numb_server( "216.146.46.59", 3478, turn_username, turn_password );

    // STUN Server - Araruama
    ICEServer araruama_server( "146.164.47.193", 3478 );

    stun_server = &numb_server;
    //stun_server = &araruama_server;
    if( use_turn )
        turn_server = &numb_server;
    else
        turn_server = NULL;

    icemgr.initialise( stun_server, turn_server );
    ICEStream* stream = icemgr.createStream( 2 );
    stream->setReceiveCallback( receive );

    lcands = stream->getLocalCandidates();
    printCandidates( lcands );
    writeCandidatesToFile( stream->getLocalUsername(), stream->getLocalPassword(), lcands, "local_candidates.txt" );
    exchangeFile( "local_candidates.txt", "remote_candidates.txt", "146.164.47.221" );
    rcands = readCandidatesFromFile( remote_username, remote_password, "remote_candidates.txt" );
    stream->setRemoteCredentials( remote_username, remote_password );
    stream->setRemoteCandidates( rcands );

    gchar msg[] = "hello world!";
    stream->send( sizeof(msg), msg, 1 );
    stream->send( sizeof(msg), msg, 2 );

    sleep(1);

    stream->release();
    icemgr.release();

    return 0;
}
